package route

import (
	"fmt"
	"net/url"
	"strings"

	"github.com/gogf/gf/v2/container/garray"

	"github.com/gogf/gf/v2/container/gmap"
	"github.com/gogf/gf/v2/encoding/gbase64"
	"github.com/gogf/gf/v2/encoding/gjson"
	"github.com/gogf/gf/v2/encoding/gurl"
	"github.com/gogf/gf/v2/frame/g"
	"github.com/gogf/gf/v2/net/ghttp"
	"github.com/gogf/gf/v2/os/gview"
	"github.com/gogf/gf/v2/text/gstr"
)

var v2_http_cache = gmap.NewStrStrMap(true)

type V2Ctrl struct {
}

func (c *V2Ctrl) V2list(r *ghttp.Request) {
	r.Response.WriteJsonExit(map[string]interface{}{
		"rows": parsecObj(getStrByRequest(r), r),
	})
}

func (c *V2Ctrl) ClashAll(r *ghttp.Request) {
	list := parsecObj(getStrByRequest(r), r)
	list = sortNodes(list, r)
	// 对 list 进行排序
	names := []string{}
	node_strs := []string{}
	for i := 0; i < len(list); i++ {
		name := list[i]["name"]
		names = append(names, name.(string))
		json_str, err := gjson.EncodeString(list[i])
		if err != nil {
			panic(err)
		}
		node_strs = append(node_strs, json_str)
	}
	name_str_jsons, err := gjson.EncodeString(names)
	if err != nil {
		panic(err)
	}
	tname := r.GetQuery("tname")
	proxy := dialerProxyWapper(list, r)
	content, err := r.GetView().ParseOption(r.Context(), gview.Option{
		File:   fmt.Sprintf("yaml/config/clash_tmp/%s.yaml", tname.String()),
		Orphan: true, Params: map[string]interface{}{
			"names":     name_str_jsons,
			"node_strs": node_strs,
			"proxy":     proxy,
		},
	})
	if err != nil {
		panic(err)
	}
	r.Response.Write(content)
}

func sortNodes(list []map[string]interface{}, r *ghttp.Request) []map[string]interface{} {
	ns := garray.NewArray()
	for i := 0; i < len(list); i++ {
		ns.Append(list[i])
	}
	ns.SortFunc(func(v1, v2 interface{}) bool {
		v1name := v1.(map[string]interface{})["name"].(string)
		v2name := v2.(map[string]interface{})["name"].(string)
		// 名称越短越靠前
		return len(v1name)-len(v2name) < 0
	})
	rst := make([]map[string]interface{}, len(list))
	for i := 0; i < len(list); i++ {
		rst[i] = ns.At(i).(map[string]interface{})
	}
	return rst
}

func dialerProxyWapper(list []map[string]interface{}, r *ghttp.Request) map[string]interface{} {
	rst := gmap.NewStrAnyMap()
	pstr := r.GetQuery("dialerProxy")
	groups := garray.NewStrArray()
	if !pstr.IsEmpty() {
		ps := strings.Split(pstr.String(), "-")
		for _, p := range ps {
			group_name := fmt.Sprintf("三级代理-%s", p)
			names := garray.NewStrArray()
			node_strs := garray.NewStrArray()
			for i := 0; i < len(list); i++ {
				row := gmap.NewStrAnyMapFrom(list[i]).Clone()
				if !strings.EqualFold(p, "DIRECT") {
					row.Set("dialer-proxy", p)
				} else {
					group_name = "直连"
				}
				name := fmt.Sprintf("%s-%s", group_name, row.Get("name"))
				row.Set("name", name)
				json_str, _ := gjson.EncodeString(row.Map())
				node_strs.Append(json_str)
				names.Append(name)
			}
			name_str_jsons, _ := gjson.EncodeString(names)
			rst.Set(group_name, map[string]interface{}{
				"names":     name_str_jsons,
				"node_strs": node_strs.Slice(),
			})
			groups.Append(group_name)
		}
	}
	group_str_jsons, _ := gjson.EncodeString(groups)
	rst.Set("groups", group_str_jsons)
	return rst.Map()
}

func getStrByRequest(r *ghttp.Request) string {
	s := `
dmxlc3M6Ly9jODJiMzc4NS05YTcxLTQxMTItOGM4Yi1lNWI5NDgxZWU1N2ZAOC4yMjEuMTQxLjE3MDoxMTcxMj9zZWN1cml0eT1yZWFsaXR5JmVuY3J5cHRpb249bm9uZSZwYms9WFRzUlF1RUt3bk1wTDQ3ZnBDYWZ1V1NCN3p5VGttVWtvcGUxWmRhUDMyUSZoZWFkZXJUeXBlPW5vbmUmZnA9cmFuZG9tJnNweD0lMkYmdHlwZT10Y3AmZmxvdz14dGxzLXJwcngtdmlzaW9uJnNuaT1hcHBsZS5jb20mc2lkPWVjMTg2MDU2NzVkMzU4ZWMjQWxpeXVuLUpQLUZRLUENCnZsZXNzOi8vMDVmODRlODQtYjJiYi00ZTJmLTk2MDMtMDJjNjlhZGU0OTEyQDguMjIxLjE0Mi4yMzQ6MTI4MTI/c2VjdXJpdHk9cmVhbGl0eSZlbmNyeXB0aW9uPW5vbmUmcGJrPVdndnpsZ3pSR1VZLU03NEhseW41X0dESnRfcHBBS3JNRV9fN1hENHB3VTgmaGVhZGVyVHlwZT1ub25lJmZwPXJhbmRvbSZzcHg9JTJGJnR5cGU9dGNwJmZsb3c9eHRscy1ycHJ4LXZpc2lvbiZzbmk9YXdzLmNvbSZzaWQ9ZWQzMjE5M2ZhZmRhM2EjQWxpeXVuLUpQLUZRLUINCnZsZXNzOi8vNGYyMmFmNGItZGVmNy00NjgwLTllMDEtY2NhOGE1MzdkYTVjQDguMjIxLjE0MC43MToxMDU4Mz9zZWN1cml0eT1yZWFsaXR5JmVuY3J5cHRpb249bm9uZSZwYms9aTFUVUdGMjQ0TG5XWTE3blBmTms5TWowb09jWTJHN2lUNkxWbnVYZG1CUSZoZWFkZXJUeXBlPW5vbmUmZnA9cmFuZG9tJnNweD0lMkYmdHlwZT10Y3AmZmxvdz14dGxzLXJwcngtdmlzaW9uJnNuaT1hd3MuY29tJnNpZD04ODVlNDM0ZWFjZjkwNjBjI0FsaXl1bi1KUC1GUS1DDQp2bGVzczovL2UzNmUzZWNkLTExNmYtNGY2NS05N2Q4LTNlOGUzMWI4OTAzZkA0Ny44My4xOTMuMjA6MTc0MTA/c2VjdXJpdHk9cmVhbGl0eSZlbmNyeXB0aW9uPW5vbmUmcGJrPUUxSFFYdkx0d0VlMVVQOHFGcUprajR3TWR2bkNuR3FUQ21BcGdSVnEtencmaGVhZGVyVHlwZT1ub25lJmZwPXJhbmRvbSZzcHg9JTJGJnR5cGU9dGNwJmZsb3c9eHRscy1ycHJ4LXZpc2lvbiZzbmk9YXBwbGUuY29tJnNpZD1iYjRhNmRiOTYxMDUjQWxpeXVuLUhLLUZRDQp2bGVzczovL2FjNTNmOWRkLTE4MzAtNDI4Yi05MjUzLThhZGUwNmEwY2MzYkA0Ny4yMzcuMTQ3LjIwNDoxMTU3MD9zZWN1cml0eT1yZWFsaXR5JmVuY3J5cHRpb249bm9uZSZwYms9SkpJcjcwOG9tWWlCZ1dNZUpzSUFIaUlvcV9Vcy16UXdYN3VST19tbnFFMCZoZWFkZXJUeXBlPW5vbmUmZnA9cmFuZG9tJnNweD0lMkYmdHlwZT10Y3AmZmxvdz14dGxzLXJwcngtdmlzaW9uJnNuaT1hcHBsZS5jb20mc2lkPWI3YzgjQWxpeXVuLVNHLUZRDQp2bGVzczovLzYxODliZWUyLWE3MTAtNGRlZS1iNTRmLTU3MThlYjU1YTBmY0A4LjIyMC4yMTkuMTA6MTEyMzk/c2VjdXJpdHk9cmVhbGl0eSZlbmNyeXB0aW9uPW5vbmUmcGJrPVBVZC1SUFB6S1lIUHh5VVc2NGIxalAtSWdCcGNRX1JWZnhrcHV2NlFqalkmaGVhZGVyVHlwZT1ub25lJmZwPXJhbmRvbSZzcHg9JTJGJnR5cGU9dGNwJmZsb3c9eHRscy1ycHJ4LXZpc2lvbiZzbmk9YXBwbGUuY29tJnNpZD04ZTFmN2E4MWNlZDgjQWxpeXVuLUtSLUZRDQp2bGVzczovL2Q3OWVmYWUxLWZmNDctNGUzNC05NDEzLTE2N2I0ZjBjZWFlY0AxMTkuMTMuNzguNzQ6MTMxNzU/c2VjdXJpdHk9cmVhbGl0eSZlbmNyeXB0aW9uPW5vbmUmcGJrPUVFQVZnaE5PbW1qdFZISTZMbjRCQVBBNzAtN09qOTVBUTVGMVhPd3V0d2smaGVhZGVyVHlwZT1ub25lJmZwPXJhbmRvbSZzcHg9JTJGJnR5cGU9dGNwJmZsb3c9eHRscy1ycHJ4LXZpc2lvbiZzbmk9YXBwbGUuY29tJnNpZD00NWExODA1MWNlI0h1YXdlaS1ISy1GUS1BDQp2bGVzczovLzg4NzFiNzAyLTgxYWEtNDYxYi1hM2RkLWUyYTdlMjI3NjAwOUAxNTkuMTM4LjMuMjA0OjExNTkxP3NlY3VyaXR5PXJlYWxpdHkmZW5jcnlwdGlvbj1ub25lJnBiaz14R0NQQWNrLVd2bF9SQWJMRkFiblZKdHA2Ymd5V0x1MkZkNFctaTJaWWkwJmhlYWRlclR5cGU9bm9uZSZmcD1yYW5kb20mc3B4PSUyRiZ0eXBlPXRjcCZmbG93PXh0bHMtcnByeC12aXNpb24mc25pPWFwcGxlLmNvbSZzaWQ9MTEyZDM3MTQ0YzZmZmIjSHVhd2VpLUhLLUZRLUINCnZsZXNzOi8vNzUxMjUwMjgtOTE3Ny00MDExLWJkZTctOTBlNDFiMGJlNWFiQDE4LjE4Mi4xNS4xMDo0MDg0MT9zZWN1cml0eT1yZWFsaXR5JmVuY3J5cHRpb249bm9uZSZwYms9LUg1Nmw2Sk5xWlJpeUVFSWdmQzhzeEpYUldwNEpQY3M3RUtWRjFSQ1FtWSZoZWFkZXJUeXBlPW5vbmUmZnA9cmFuZG9tJnNweD0lMkYmdHlwZT10Y3AmZmxvdz14dGxzLXJwcngtdmlzaW9uJnNuaT1hcHBsZS5jb20mc2lkPWYxI0pQLUZRLUENCnZsZXNzOi8vNWE3ZjFmYmUtYTdkOC00ZGRhLTk4MGMtZmNlYjRjMGFhNWNjQDEzLjIzMC4xMjguMjY6MTgzNzM/c2VjdXJpdHk9cmVhbGl0eSZlbmNyeXB0aW9uPW5vbmUmcGJrPXpzdUlfemVua0NfZTA0UWluakdyQmx5MXV4cTRZXzNYVEU4TDVTZnIzekEmaGVhZGVyVHlwZT1ub25lJmZwPXJhbmRvbSZzcHg9JTJGJnR5cGU9dGNwJmZsb3c9eHRscy1ycHJ4LXZpc2lvbiZzbmk9YXBwbGUuY29tJnNpZD1iYWJjI0pQLUZRLUINCnZsZXNzOi8vYjdlYjczNWQtMGYzOC00OTJmLTlmMzUtNDQxNjc4NjZmYWM0QDE4LjE0MS4yMzUuOTk6MzEwNjI/c2VjdXJpdHk9cmVhbGl0eSZlbmNyeXB0aW9uPW5vbmUmcGJrPUtrSG1TbXJaMlZXYjdtTk9IdlFway1tTnk0ME9BTUMtd1dYTnp1cFgzVUkmaGVhZGVyVHlwZT1ub25lJmZwPXJhbmRvbSZzcHg9JTJGJnR5cGU9dGNwJmZsb3c9eHRscy1ycHJ4LXZpc2lvbiZzbmk9YXBwbGUuY29tJnNpZD0zMDI2NThlMyNTRy1GUS1BDQp2bGVzczovLzYwNzY3NTg1LTdhNjMtNGFmNS04ZTk0LTliMzk3M2QyMzYwOUA1NC4xNjkuMTE3LjE5MToxMjk3MD9zZWN1cml0eT1yZWFsaXR5JmVuY3J5cHRpb249bm9uZSZwYms9ak0zYTc1WmZMTnNUX05wZF9yOFpmaTJNZmRzLUV3NVZUSzNxOENqemxqQSZoZWFkZXJUeXBlPW5vbmUmZnA9cmFuZG9tJnNweD0lMkYmdHlwZT10Y3AmZmxvdz14dGxzLXJwcngtdmlzaW9uJnNuaT1hcHBsZS5jb20mc2lkPWQ1YjcyYzRmI1NHLUZRLUINCnZsZXNzOi8vZGEyNDU3OTYtZjdhNC00NzQwLTlmZDAtODBkYjQ2Yjg0YzdmQDMuMzYuOTkuODU6MjM2NzU/c2VjdXJpdHk9cmVhbGl0eSZlbmNyeXB0aW9uPW5vbmUmcGJrPWphVWhjUXNtbVpMN0h3XzJsMmMtSWZzTlZUWWliSWpBTTJMZnpsSUxjQ2smaGVhZGVyVHlwZT1ub25lJmZwPXJhbmRvbSZzcHg9JTJGJnR5cGU9dGNwJnNuaT1hcHBsZS5jb20mc2lkPTc4YjY1YzA1YjkxNjZmNTYjS1ItRlEtQQ0Kdmxlc3M6Ly9iNTE4ODdjMC04Yzg4LTRhNGEtYjdhYi01MWU0MDcyNGNhMGFAMy4zOC4yMTEuNjM6MTQ1MDg/c2VjdXJpdHk9cmVhbGl0eSZlbmNyeXB0aW9uPW5vbmUmcGJrPXhRS0Q0MEU2Qkk2czh5dDlIU1pPNWRZS1cxN19oUUJURmo0MFdneVNsWE0maGVhZGVyVHlwZT1ub25lJmZwPXJhbmRvbSZzcHg9JTJGJnR5cGU9dGNwJmZsb3c9eHRscy1ycHJ4LXZpc2lvbiZzbmk9YXBwbGUuY29tJnNpZD04YmNhMjViOGNlI0tSLUZRLUINCnZsZXNzOi8vZTMzOWEyMjMtYjYzZi00ZGNlLTgwODgtODU3MGM5MjhiNWFjQDM0LjIyMS4xNzEuNDk6MjI0NDk/c2VjdXJpdHk9cmVhbGl0eSZlbmNyeXB0aW9uPW5vbmUmcGJrPUFhd25BQ0ZwNEI3QmZST2trV25yMC1KTGsxNGtNY3JNQ2QwbkZic0tvazAmaGVhZGVyVHlwZT1ub25lJmZwPXJhbmRvbSZzcHg9JTJGJnR5cGU9dGNwJnNuaT1hcHBsZS5jb20mc2lkPTI1YTBjNzY3YTgjVVMtRlEtQQ0Kdmxlc3M6Ly9jYzkyNWI1NS1iNGQ0LTQyMTEtYTdjZi1iNjU5ZWRlYmEwZTZAMzQuMjE3Ljg4LjM0OjIwMDk2P3NlY3VyaXR5PXJlYWxpdHkmZW5jcnlwdGlvbj1ub25lJnBiaz0yekdjYzNZZFBqaGlHWHFnamF1a3AxSmlMQmYyTkRBWUZ6R0ttdUVTZ0g0JmhlYWRlclR5cGU9bm9uZSZmcD1yYW5kb20mc3B4PSUyRiZ0eXBlPXRjcCZmbG93PXh0bHMtcnByeC12aXNpb24mc25pPWFwcGxlLmNvbSZzaWQ9MzgzMGE0NTVjNTIyI1VTLUZRLUINCnZsZXNzOi8vYTRhZWYyZTYtMzM4Ni00NzdjLWFiZmYtZmM2MGRjMjM1NzBjQDguMTM0Ljg2LjUwOjgwP3BhdGg9JTJGRHZ1c2k0U2dpOUlldmpRbiZzZWN1cml0eT1ub25lJmVuY3J5cHRpb249bm9uZSZ0eXBlPXdzI0FsaXl1bislRTUlQjklQkYlRTUlQjclOUUrODAlRTclQUIlQUYlRTUlOEYlQTMrJTI4JUU1JTg1JThEJUU2JUI1JTgxJUU3JTk0JUE4JUU2JTg4JUI3JUU0JUJEJUJGJUU3JTk0JUE4JTI5DQp2bGVzczovL2ZmYjk2ZDE0LTQ4NWUtNDkyNC04MmUxLTYxNzI5NDVhODllMUA4LjEzNC44Ni41MDo0NDM/cGF0aD0lMkZTaHVPOTJXYmpJczFOJnNlY3VyaXR5PW5vbmUmZW5jcnlwdGlvbj1ub25lJnR5cGU9d3MjQWxpeXVuKyVFNSVCOSVCRiVFNSVCNyU5RSs0NDMlRTclQUIlQUYlRTUlOEYlQTMrJTI4JUU1JTg1JThEJUU2JUI1JTgxJUU3JTk0JUE4JUU2JTg4JUI3JUU0JUJEJUJGJUU3JTk0JUE4JTI5DQp2bGVzczovL2YxNTI4MzcwLWFiMzctNDAxNS05MzU2LWE5ZDNlMGI1MmQ0OEA4LjEzNC44Ni41MDo4MDgwP3BhdGg9JTJGS3N5NjBRYmoxVnNqUWk3SSZzZWN1cml0eT1ub25lJmVuY3J5cHRpb249bm9uZSZ0eXBlPXdzI0FsaXl1bislRTUlQjklQkYlRTUlQjclOUUrODA4MCVFNyVBQiVBRiVFNSU4RiVBMyslMjglRTUlODUlOEQlRTYlQjUlODElRTclOTQlQTglRTYlODglQjclRTQlQkQlQkYlRTclOTQlQTglMjk=
`
	remote := r.GetQuery("remote")
	if "true" == remote.String() {
		url := r.GetQuery("url")
		s = v2_http_cache.GetOrSetFuncLock(url.String(), func() string {
			rp, err := g.Client().Get(r.GetCtx(), url.String())
			if err != nil {
				return ""
			}
			return rp.ReadAllString()
		})
	}
	return s
}

func parsecObj(s string, r *ghttp.Request) (list []map[string]interface{}) {
	//dric := r.GetQuery("dialerProxy")
	bs, err := gbase64.DecodeString(gstr.Trim(s))
	if err != nil {
		panic(err)
	}
	lines := gstr.Split(gstr.Trim(string(bs)), "\n")
	for i := range lines {
		m := gmap.NewStrAnyMap()
		u := gstr.Trim(lines[i])
		//nameend := gstr.Split(url, "#")
		r, err := gurl.ParseURL(u, -1)
		if err != nil {
			panic(err)
		}
		q, err := url.ParseQuery(r["query"])
		if err != nil {
			panic(err)
		}
		qm := gmap.New()
		for key, values := range q {
			if len(values) > 0 {
				qm.Set(key, values[0])
			}
		}
		m.Set("u", u)
		m.Set("qm", qm)
		basic := map[string]interface{}{
			"type": r["scheme"], "uuid": r["user"], "server": r["host"], "port": r["port"], "name": r["fragment"], "network": qm.Get("type"),
			"client-fingerprint": "chrome", "tls": false, "skip-cert-verify": true, "udp": true,
		}
		//if dric != nil {
		//	basic["dialer-proxy"] = dric.String()
		//}
		if "ws" == basic["network"] {
			wsopts := map[string]interface{}{
				"path": "/",
			}
			if qm.Contains("host") {
				wsopts["headers"] = map[string]interface{}{
					"Host": qm.Get("host"),
				}
			}
			if qm.Contains("path") {
				wsopts["path"] = qm.Get("path")
			}
			basic["ws-opts"] = wsopts
		}
		if qm.Contains("security") {
			if "reality" == qm.Get("security") {
				basic["tls"] = true
				basic["flow"] = qm.Get("flow")
				basic["servername"] = qm.Get("sni")
				basic["reality-opts"] = map[string]interface{}{
					"public-key": qm.Get("pbk"), "short-id": qm.Get("sid"),
				}
			}
		}
		if basic["network"] == "tcp" {
			// 开启TCP快速握手和多路复用
			basic["tfo"] = true
			//basic["smux"] = map[string]interface{}{
			//	"enabled": true, "protocol": "smux", "max-connections": 4,
			//	"min-streams": 4, "max-streams": 0, "statistic": false, "only-tcp": false,
			//}
		}
		list = append(list, basic)
	}
	return list
}
